package com.jandar.logging.impl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;

import com.jandar.logging.BaseLogger;
import com.jandar.logging.Logger;
import com.jandar.logging.LoggerFactory;

/**
 * 文件Logger。
 * 
 * @author pqj
 * @version 2009-7-9
 */
public class FileLogger extends BaseLogger {

	private File file = null;

	public FileLogger(String name) {
		super(name);
		file = getDirLogFile(LoggerFactory.getFilePath());
	}

	public void error(String str) {
		print(str, Logger.ERROR_MSG);
	}

	public void error(Throwable ex) {
		print(ex, Logger.ERROR_MSG);
	}

	public void info(String str) {
		print(str, Logger.INFO_MSG);
	}

	public void info(Throwable ex) {
		print(ex, Logger.INFO_MSG);
	}

	public void waring(String str) {
		print(str, Logger.WARING_MSG);
	}

	public void waring(Throwable ex) {
		print(ex, Logger.WARING_MSG);
	}

	public void debug(String str) {
		if (LoggerFactory.isDebug()) {
			print(str, Logger.DEBUG_MSG);
		}
	}

	public void debug(Throwable ex) {
		if (LoggerFactory.isDebug()) {
			print(ex, Logger.DEBUG_MSG);
		}
	}

	public synchronized File getFile() {
		return file;
	}

	/**
	 * 查找指定目录下最近使用的日志文件。
	 * 
	 * @param path 目录
	 * @return 日志文件
	 */
	public static synchronized File getDirLogFile(String path) {
		String[] files = new File(path).list(new FilenameFilter() {

			public boolean accept(File dir, String name) {
				return (name.endsWith(LoggerFactory.getFileExpandName())) ? true : false;
			}
		});

		// 文件夹为空
		if (files == null || files.length == 0) {
			return null;
		}

		// 找到最近使用的文件
		String maxName = files[0];
		for (int i = 1; i < files.length; ++i) {
			if (maxName.compareTo(files[i]) < 0) {
				maxName = files[i];
			}
		}
		File maxFile = new File(LoggerFactory.getFilePath() + maxName);
		return maxFile;
	}

	private void print(String text, String option) {
		PrintStream stream = null;
		try {
			stream = getPrintStream();
			stream.println(super.format(option, text));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (stream != null) {
				stream.close();
			}
		}
	}

	private void print(Throwable ex, String option) {
		PrintStream stream = null;
		try {
			stream = getPrintStream();
			stream.println(super.format(option, ex));
			ex.printStackTrace(stream);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (stream != null) {
				stream.close();
			}
		}
	}

	private synchronized PrintStream getPrintStream() throws UnsupportedEncodingException,
			FileNotFoundException {
		if ((file == null)
				|| (LoggerFactory.isManyFiles() && file.length() >= LoggerFactory.getFileSize())
				|| !file.exists()) {

			file = LoggerFactory.getLogFile();
			while (file.exists()) {
				try {
					Thread.sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				file = LoggerFactory.getLogFile();
			}
			createFile(file.getAbsolutePath(), file.getAbsolutePath().length());
		}

		return new PrintStream(new FileOutputStream(file, true), LoggerFactory.isAutoflush(),
				LoggerFactory.getEncoding());
	}

	private static boolean createFile(String name, int index) {
		String name1 = name.substring(0, index);
		File file1 = new File(name1);
		boolean ret = false;
		if (file1.exists()) {
			return true;
		}
		int i;
		for (i = index - 1; i > 1; --i) {
			if (name.charAt(i) == '/' || name.charAt(i) == '\\') {
				break;
			}
		}
		if (i > 1) {
			ret = createFile(name, i);
		}
		String name2 = name.substring(0, index);
		File file2 = new File(name2);
		if (!file2.exists()) {
			if (name.length() == index && name.indexOf('.') != -1) {
				try {
					ret = file2.createNewFile();
				} catch (IOException e) {
					e.printStackTrace();
				}
			} else {
				ret = file2.mkdir();
			}
		}
		return ret;
	}
}
